﻿using Microsoft.EntityFrameworkCore.ChangeTracking;
using SBlogCore.Common.App;
using SBlogCore.Common.DatabaseAccessor.Entitys;
using SBlogCore.Common.Snowflake;

namespace SBlogCore.Common.DatabaseAccessor.Repositorys.EFCore
{
    [SkipScan]
    public partial class Repository<TEntity> where TEntity : class, IBaseEntity
    {
        /// <summary>
        /// 插入
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public TEntity Insert(TEntity entity)
        {
            var res= AddOne(entity);
            return res.Entity;
        }
        /// <summary>
        /// 插入数据立即保存
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public int InsertNow(TEntity entity)
        {
            AddOne(entity);
            return SaveChanges();
        }
        /// <summary>
        /// 异步插入
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async ValueTask<TEntity> InsertAsync(TEntity entity)
        {
            var res=await AddOneAsync(entity);
            return res.Entity;
        }
        /// <summary>
        /// 异步插入数据立即保存
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async ValueTask<TEntity> InsertNowAsync(TEntity entity)
        {
            var res =await AddOneAsync(entity);
            await SaveChangesAsync();
            return res.Entity;
        }

        /// <summary>
        /// 异步批量插入
        /// </summary>
        /// <param name="entityParams"></param>
        /// <returns></returns>
        public Task InsertRangeAsync(IEnumerable<TEntity> entityParams)
        {
            return AddMoreAsync(entityParams);
        }

        /// <summary>
        /// 批量插入立即保存
        /// </summary>
        /// <param name="entityParams"></param>
        /// <returns></returns>
        public int InsertRangeNow(IEnumerable<TEntity> entityParams)
        {
            AddMore(entityParams);
            return SaveChanges();
        }

        /// <summary>
        /// 异步批量插入立即保存
        /// </summary>
        /// <param name="entityParams"></param>
        /// <returns></returns>
        public Task<int> InsertRangeNowAsync(IEnumerable<TEntity> entityParams)
        {
            AddMoreAsync(entityParams);
            return SaveChangesAsync();
        }

        private EntityEntry<TEntity> AddOne(TEntity entity)
        {
            EntityWork(entity);
            return Entities.Add(entity);
        }

        private ValueTask<EntityEntry<TEntity>> AddOneAsync(TEntity entity)
        {
            EntityWork(entity);
            return Entities.AddAsync(entity);
        }

        private void AddMore(IEnumerable<TEntity> entityParams)
        {
            var baseEntities = entityParams as TEntity[] ?? entityParams.ToArray();
            MoreEntityWork(baseEntities);
            Entities.AddRange(baseEntities);
        }

        private Task AddMoreAsync(IEnumerable<TEntity> entityParams)
        {
            var baseEntities = entityParams as TEntity[] ?? entityParams.ToArray();
            MoreEntityWork(baseEntities);
            return Entities.AddRangeAsync(baseEntities);
        }

        private  void MoreEntityWork(IEnumerable<TEntity> entityParams)
        {
            foreach (var entity in entityParams)
            {
                EntityWork(entity);
            }
        }

        private static void EntityWork(TEntity entity)
        {
            if (entity is not BaseEntity baseEntity) return;
            if (baseEntity.Id == 0)
            {
                baseEntity.Id = IDGenerator.NextId();
            }
            if (baseEntity is not CreateEntity createEntity) return;
            var token = AppBase.GetJwtUser();
            if (token == null) return;
            createEntity.CreatedTime ??= DateTime.Now;
            createEntity.CreatedUserId ??= token.Uid;
            createEntity.PlantId ??= token.PlantId;
            createEntity.SysOrgId ??= token.OrgId;
        }
    }
}
